# -*- coding: utf-8 -*-
# @version        : 1.0
# @Create Time    : 2025/03/31 16:48
# @File           : crud.py
# @IDE            : PyCharm
# @desc           : 从excel文件中获取模拟数据

import asyncio
import json
from pathlib import Path
from application.settings import STATIC_ROOT
from utils.excel.excel_manage import ExcelManage


class GenerateMockData:
    """
    从Excel文件中生成模拟数据
    """

    EXCEL_DIR = STATIC_ROOT / 'dispatch' / 'taskpool'
    

    def __init__(self, file = None):
        if not self.EXCEL_DIR.exists():
            self.EXCEL_DIR.mkdir()

        self.files = []

        if file and Path(file).exists():
            self.files = [file]
        else:
            self.files = [f for f in self.EXCEL_DIR.rglob('*.xlsx')]
        self.datas = {}
        self.__serializer_data()

    def __serializer_data(self):
        """
        序列化数据，将excel数据转为python对象
        """
        for file in sorted(self.files, key=lambda x: x.stat().st_ctime, reverse=True):
            ex = ExcelManage()
            ex.open_workbook(file, read_only=True)
            sheet_names = ex.get_sheets()
            self.__get_sheet_data(ex, sheet_names)

    def __get_sheet_data(self, ex, sheet_names):
        """
        获取工作区数据
        """
        for sheet in sheet_names:
            sheet_data = []
            ex.open_sheet(sheet)
            headers = ex.get_header()
            datas = ex.readlines(min_row=2, max_col=len(headers))
            for row in datas:
                sheet_data.append(dict(zip(headers, row)))
            if sheet not in self.datas:
                self.datas[sheet] = []
            self.datas[sheet] += sheet_data

    async def __generate_data(self, sheet_name: str):
        """
        生成数据

        :param sheet_name: 表名
        """
        datas = []
        for data in self.datas.get(sheet_name, []):
            for key, value in data.items():
                if isinstance(value, str) and value.startswith("[") and value.endswith("]"):
                    try:
                        data[key] = json.loads(value)
                    except Exception:
                        raise
            datas.append(data)
        # print(f"{sheet_name} 表数据已生成")
        return datas

    async def generate_dispatch_mock_data(self, sheet_name, unique_key=None, map_dict=None, **params):
        """
        生成调度相关模拟数据
        """
        datas = await self.__generate_data(sheet_name)
        datas = self.__filter_by_unique(datas, unique_key)
        datas = self.__convert_data(datas, map_dict)
        datas = self.__filter_by_unique(datas, unique_key)
        datas = self.__filter_by_params(datas, **params)
        return datas, len(datas)
    
    def __filter_by_unique(self, datas, uniq_key):
        uniq_set = set()
        results = []
        if uniq_key:
            for data in datas:
                if data.get(uniq_key) and data.get(uniq_key) in uniq_set:
                    continue
                results.append(data)
        else:
            results = datas
        return results
    
    def __convert_data(self, datas, map_dict):
        results = []
        if not map_dict:
            map_dict = {}
        for data in datas:
            r = {}
            for key, value in data.items():
                if key.startswith("是否"):
                    if isinstance(value, str) and (value == "是" or value.lower() == "true"):
                        value = 1
                    elif isinstance(value, str) and (value == "否" or value.lower() == "false"):
                        value = 0
                elif value is None or value == "None" or value == "":
                    value = None
                elif value:
                    value = str(value)
                if key in map_dict:
                    key = map_dict[key]
                r[key] = value
            results.append(r)
        return results

    def __filter_by_params(self, datas, page=None, limit=None, **params):
        results = []
        if params:
            for data in datas:
                skip = False
                for key, value in params.items():
                    if value and key in data and str(value) != str(data[key]):
                        skip = True
                if skip:
                    continue
                results.append(data)
        else:
            results = datas

        page = page or params.get("page") or 1
        limit = limit or params.get("limit")
        if page and limit:
            results = results[(page - 1) * limit: min(page * limit, len(results))]
        return results
        

if __name__ == "__main__":
    gm = GenerateMockData()
    sheet_data = asyncio.run(gm.generate_dispatch_mock_data("工单列表"))
    print(sheet_data)
